package com.lwgk.network;

import android.content.Context;
import android.content.Intent;
import android.support.annotation.Nullable;
import android.text.TextUtils;
import com.lwgk.AppComplication;
import com.lwgk.R;
import com.lwgk.been.ResponseBean;
import com.lwgk.constant.ConstantUtils;
import com.lwgk.mvp.view.LoginActivity;
import com.lwgk.utils.AppManagerUtils;
import com.lwgk.utils.GsonUtils;
import com.lwgk.utils.NetConnectUtils;
import com.lwgk.utils.ToastUtils;
import com.lzy.okgo.OkGo;
import com.lzy.okgo.cache.CacheEntity;
import com.lzy.okgo.cache.CacheMode;
import com.lzy.okgo.callback.StringCallback;
import com.lzy.okgo.model.Response;
import com.lzy.okgo.request.GetRequest;
import com.lzy.okgo.request.PostRequest;

import org.greenrobot.greendao.annotation.NotNull;

import java.net.SocketException;
import java.net.SocketTimeoutException;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLSession;

import okhttp3.OkHttpClient;

/**
 * created by 赵航
 * 联系微信 微信号：zhao--hang--
 * on 2019/7/22
 * --------------------------------------------------------------------------
 * 描述：okgo的封装，网络请求不需要判断是否有网
 * 注意事项：封装网络请求，针对String字符串再解析数据，现在都是不采用缓存
 * <p>
 * 按照HTTP协议的默认缓存规则，例如有304响应头时缓存
 * DEFAULT,
 * <p>
 * 不使用缓存
 * NO_CACHE,
 * <p>
 * 请求网络失败后，读取缓存
 * REQUEST_FAILED_READ_CACHE
 * <p>
 * 如果缓存不存在才请求网络，否则使用缓存
 * IF_NONE_CACHE_REQUEST
 * <p>
 * 先使用缓存，不管是否存在，仍然请求网络
 * FIRST_CACHE_THEN_REQUEST
 **/
public class OkGoUtils {

    private static Context mContext;

    public static void getInstance(AppComplication complication) {
        mContext = complication;
        //---------这里给出的是示例代码,告诉你可以这么传,实际使用的时候,根据需要传,不需要就不传-------------//
        //        HttpHeaders headers = new HttpHeaders();
        //        headers.put("commonHeaderKey1", "commonHeaderValue1");    //header不支持中文，不允许有特殊字符
        //        headers.put("commonHeaderKey2", "commonHeaderValue2");


        //        HttpParams params = new HttpParams();
        //        params.put("commonParamsKey1", "commonParamsValue1");     //param支持中文,直接传,不要自己编码
        //        params.put("commonParamsKey2", "这里支持中文参数");
        //----------------------------------------------------------------------------------------//

        OkHttpClient.Builder builder = new OkHttpClient.Builder();
        //log相关
        //HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor("OkGo");
        //loggingInterceptor.setPrintLevel(HttpLoggingInterceptor.Level.BODY);        //log打印级别，决定了log显示的详细程度
        //loggingInterceptor.setColorLevel(Level.INFO);                               //log颜色级别，决定了log在控制台显示的颜色
        //builder.addInterceptor(loggingInterceptor);                                 //添加OkGo默认debug日志
        //第三方的开源库，使用通知显示当前请求的log，不过在做文件下载的时候，这个库好像有问题，对文件判断不准确
        //builder.addInterceptor(new ChuckInterceptor(this));

        //超时时间设置，默认60秒
        builder.readTimeout(OkGo.DEFAULT_MILLISECONDS, TimeUnit.MILLISECONDS);      //全局的读取超时时间
        builder.writeTimeout(OkGo.DEFAULT_MILLISECONDS, TimeUnit.MILLISECONDS);     //全局的写入超时时间
        builder.connectTimeout(OkGo.DEFAULT_MILLISECONDS, TimeUnit.MILLISECONDS);   //全局的连接超时时间

        //自动管理cookie（或者叫session的保持），以下几种任选其一就行
        //builder.cookieJar(new CookieJarImpl(new SPCookieStore(this)));            //使用sp保持cookie，如果cookie不过期，则一直有效
        //builder.cookieJar(new CookieJarImpl(new DBCookieStore(complication)));              //使用数据库保持cookie，如果cookie不过期，则一直有效
        //builder.cookieJar(new CookieJarImpl(new MemoryCookieStore()));            //使用内存保持cookie，app退出后，cookie消失

        //https相关设置，以下几种方案根据需要自己设置
        //方法一：信任所有证书,不安全有风险
        //HttpsUtils.SSLParams sslParams1 = HttpsUtils.getSslSocketFactory();
        //方法二：自定义信任规则，校验服务端证书
        //HttpsUtils.SSLParams sslParams2 = HttpsUtils.getSslSocketFactory(new SafeTrustManager());
        //方法三：使用预埋证书，校验服务端证书（自签名证书）
        //HttpsUtils.SSLParams sslParams3 = HttpsUtils.getSslSocketFactory(getAssets().open("srca.cer"));
        //方法四：使用bks证书和密码管理客户端证书（双向认证），使用预埋证书，校验服务端证书（自签名证书）
        //HttpsUtils.SSLParams sslParams4 = HttpsUtils.getSslSocketFactory(getAssets().open("xxx.bks"), "123456", getAssets().open("yyy.cer"));
        //builder.sslSocketFactory(sslParams1.sSLSocketFactory, sslParams1.trustManager);
        //配置https的域名匹配规则，详细看demo的初始化介绍，不需要就不要加入，使用不当会导致https握手失败
        builder.hostnameVerifier(new SafeHostnameVerifier());

        // 其他统一的配置
        // 详细说明看GitHub文档：https://github.com/jeasonlzy/
        OkGo.getInstance().init(complication)                           //必须调用初始化
                .setOkHttpClient(builder.build())               //建议设置OkHttpClient，不设置会使用默认的
                .setCacheMode(CacheMode.NO_CACHE)               //全局统一缓存模式，默认不使用缓存，可以不传
                .setCacheTime(CacheEntity.CACHE_NEVER_EXPIRE)   //全局统一缓存时间，默认永不过期，可以不传
                .setRetryCount(4);                            //全局统一超时重连次数，默认为三次，那么最差的情况会请求4次(一次原始请求，三次重连请求)，不需要可以设置为0
        //                .addCommonHeaders(headers);                      //全局公共头
        //                .addCommonParams(params);                       //全局公共参数

    }

    //植入主机拦截器，如果跟主机一样可以进行网络请求，否则不可以
    private static class SafeHostnameVerifier implements HostnameVerifier {
        @Override
        public boolean verify(String hostname, SSLSession session) {
            return hostname.equals("www.932edu.com");
        }
    }

    /**
     * @param url      请求的Uri
     * @param map      传递的键值对
     * @param callback 接口回调，仅限于普通的接口对字符串的请求，返回json字符串
     */
    public static void getRequets(@NotNull String url, @Nullable Map<String, String> map,@NotNull final OkgoCallBack callback) {

        GetRequest<String> stringGetRequest = OkGo.<String>get(url)
                .tag(url)
                .headers("header1", "headerValue1")
                .cacheMode(CacheMode.REQUEST_FAILED_READ_CACHE);//先请求网络，网络请求成功后，就不取缓存，网络请求失败后，就取缓存

        if (map != null) {
            stringGetRequest.params(map);
        }

        stringGetRequest.execute(new StringCallback() {
            @Override
            public void onSuccess(Response<String> response) {
                String body = response.body();
                //json解析异常
                if (body == null || TextUtils.isEmpty(body)) {
                    callback.onFailure(AppComplication.mContext.getString(R.string.json_error), ConstantUtils.NETERRORZERO);
                    return;
                }
                ResponseBean responseBean = GsonUtils.parseJsonToBean(body, ResponseBean.class);
                //json解析异常
                if (responseBean == null) {
                    callback.onFailure(AppComplication.mContext.getString(R.string.json_error), ConstantUtils.NETERRORZERO);
                    return;
                }

                //json请求成功后
                if (TextUtils.equals(responseBean.getCode(), ConstantUtils.RESULTOK)) {
                    callback.onSuccess(body);
                } else if (TextUtils.equals(responseBean.getCode(), ConstantUtils.NEEDLOGIN)) {
                    Intent intent = new Intent();
                    AppManagerUtils.getInstance().finishTopActivity();
                    intent.setClass(mContext, LoginActivity.class);
                    mContext.startActivity(intent);

                } else {

                    callback.onFailure(responseBean.getMsg(), ConstantUtils.RESULTERROR);
                }


            }

            @Override
            public void onError(Response<String> response) {
                super.onError(response);
                Throwable exception = response.getException();
                if (exception instanceof SocketTimeoutException) {
                    callback.onFailure(AppComplication.mContext.getString(R.string.net_overtime), ConstantUtils.NETERRORONE);
                } else if (exception instanceof SocketException) {
                    callback.onFailure(AppComplication.mContext.getString(R.string.server_error), ConstantUtils.NETERRORTWO);
                }
                callback.onFailure(AppComplication.mContext.getString(R.string.net_error), ConstantUtils.NETERRORTHREE);
            }

            //读取缓存数据
            @Override
            public void onCacheSuccess(Response<String> response) {
                super.onCacheSuccess(response);
                String body = response.body();
                //json解析异常
                if (body == null || TextUtils.isEmpty(body)) {
                    callback.onFailure(AppComplication.mContext.getString(R.string.json_error), ConstantUtils.NETERRORZERO);
                    return;
                }
                ResponseBean responseBean = GsonUtils.parseJsonToBean(body, ResponseBean.class);
                //json解析异常
                if (responseBean == null) {
                    callback.onFailure(AppComplication.mContext.getString(R.string.json_error), ConstantUtils.NETERRORZERO);
                    return;
                }

                if (TextUtils.equals(responseBean.getCode(), ConstantUtils.RESULTOK)) {
                    callback.onSuccess(body);
                } else if (TextUtils.equals(responseBean.getCode(), ConstantUtils.NEEDLOGIN)) {
                    Intent intent = new Intent();
                    intent.setClass(mContext, LoginActivity.class);
                    AppManagerUtils.getInstance().finishTopActivity();
                    mContext.startActivity(intent);
                }

                //当无网时，
                if (!NetConnectUtils.isNetConnected()) {
                    ToastUtils.showIntTost(R.string.net_error);
                }

            }
        });

    }

    /**
     * @param url      请求的uri
     * @param map      请求的键值对
     * @param callback 请求的返回json字符串
     */
    public static void postRequets(@NotNull String url, @Nullable Map<String, String> map,@NotNull final OkgoCallBack callback) {
        PostRequest<String> stringPostRequest = OkGo.<String>post(url)
                .tag(url)
                .headers("header1", "headerValue1")
                .cacheMode(CacheMode.REQUEST_FAILED_READ_CACHE);
        if (map != null) {
            stringPostRequest.params(map);
        }
        stringPostRequest.execute(new StringCallback() {
            @Override
            public void onSuccess(Response<String> response) {
                String body = response.body();
                //json解析异常
                if (body == null || TextUtils.isEmpty(body)) {
                    callback.onFailure(AppComplication.mContext.getString(R.string.json_error), ConstantUtils.NETERRORZERO);
                    return;
                }
                ResponseBean responseBean = GsonUtils.parseJsonToBean(body, ResponseBean.class);
                //json解析异常
                if (responseBean == null) {
                    callback.onFailure(AppComplication.mContext.getString(R.string.json_error), ConstantUtils.NETERRORZERO);
                    return;
                }

                //json解析成功后
                if (TextUtils.equals(responseBean.getCode(), ConstantUtils.RESULTOK)) {
                    callback.onSuccess(body);
                } else if (TextUtils.equals(responseBean.getCode(), ConstantUtils.NEEDLOGIN)) {
                    Intent intent = new Intent();
                    intent.setClass(mContext, LoginActivity.class);
                    AppManagerUtils.getInstance().finishTopActivity();
                    mContext.startActivity(intent);
                } else {
                    callback.onFailure(responseBean.getMsg(), ConstantUtils.RESULTERROR);
                }

            }

            @Override
            public void onError(Response<String> response) {
                super.onError(response);
                Throwable exception = response.getException();
                if (exception instanceof SocketTimeoutException) {
                    callback.onFailure(AppComplication.mContext.getString(R.string.net_overtime), ConstantUtils.NETERRORONE);
                } else if (exception instanceof SocketException) {
                    callback.onFailure(AppComplication.mContext.getString(R.string.server_error), ConstantUtils.NETERRORTWO);
                }
                callback.onFailure(AppComplication.mContext.getString(R.string.net_error), ConstantUtils.NETERRORTHREE);
            }

            //读取缓存数据
            @Override
            public void onCacheSuccess(Response<String> response) {
                super.onCacheSuccess(response);
                String body = response.body();
                //json解析异常
                if (body == null || TextUtils.isEmpty(body)) {
                    callback.onFailure(AppComplication.mContext.getString(R.string.json_error), ConstantUtils.NETERRORZERO);
                    return;
                }
                ResponseBean responseBean = GsonUtils.parseJsonToBean(body, ResponseBean.class);
                //json解析异常
                if (responseBean == null) {
                    callback.onFailure(AppComplication.mContext.getString(R.string.json_error), ConstantUtils.NETERRORZERO);
                    return;
                }
                if (TextUtils.equals(responseBean.getCode(), ConstantUtils.RESULTOK)) {
                    callback.onSuccess(body);
                } else if (TextUtils.equals(responseBean.getCode(), ConstantUtils.NEEDLOGIN)) {
                    Intent intent = new Intent();
                    AppManagerUtils.getInstance().finishTopActivity();
                    intent.setClass(mContext, LoginActivity.class);
                    mContext.startActivity(intent);
                }
                //当无网时，
                if (!NetConnectUtils.isNetConnected()) {
                    ToastUtils.showIntTost(R.string.net_error);
                }
            }
        });


    }
    /**
     * 上传文件，多文件，混合上传等
     */
    public static void formUpload(@NotNull String uri, @Nullable Map map,@NotNull List files,@NotNull final OkgoCallBack callback) {
        if (NetConnectUtils.isNetConnected()) {
            PostRequest<String> headers = OkGo.<String>post(uri)//
                    .tag(uri)//
                    .headers("header1", "headerValue1");
            if (map != null) {
                headers.params(map);
            }
            headers.addFileParams("file", files)           // 这种方式为同一个key，上传多个文件
                    .execute(new StringCallback() {
                        @Override
                        public void onSuccess(Response<String> response) {
                            String body = response.body();
                            //json解析异常
                            if (body == null || TextUtils.isEmpty(body)) {
                                callback.onFailure(AppComplication.mContext.getString(R.string.json_error), ConstantUtils.NETERRORZERO);
                                return;
                            }
                            ResponseBean responseBean = GsonUtils.parseJsonToBean(body, ResponseBean.class);
                            //json解析异常
                            if (responseBean == null) {
                                callback.onFailure(AppComplication.mContext.getString(R.string.json_error), ConstantUtils.NETERRORZERO);
                                return;
                            }
                            //json解析成功后
                            if (TextUtils.equals(responseBean.getCode(), ConstantUtils.RESULTOK)) {
                                callback.onSuccess(body);
                            } else {
                                callback.onFailure(responseBean.getMsg(), ConstantUtils.RESULTERROR);
                            }

                        }

                        @Override
                        public void onError(Response<String> response) {
                            super.onError(response);
                            Throwable exception = response.getException();
                            if (exception instanceof SocketTimeoutException) {
                                callback.onFailure(AppComplication.mContext.getString(R.string.net_overtime), ConstantUtils.NETERRORONE);
                            } else if (exception instanceof SocketException) {
                                callback.onFailure(AppComplication.mContext.getString(R.string.server_error), ConstantUtils.NETERRORTWO);
                            }
                            callback.onFailure(AppComplication.mContext.getString(R.string.net_error), ConstantUtils.NETERRORTHREE);
                        }
                    });
        } else {
            callback.onFailure(AppComplication.mContext.getString(R.string.net_error), ConstantUtils.NETERRORTHREE);
        }
    }


    /**
     * @param url 结束指定的网络请求uri
     */
    public static void finshTogOkgo(@NotNull String url) {
        //Activity销毁时，取消网络请求
        OkGo.getInstance().cancelTag(url);
    }

}
